﻿package net.wangit.dev.wizard;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.wangit.LabelUtil;
import net.wangit.context.ActionContext;
import net.wangit.dev.ConsoleDomainUtil;
import net.wangit.dev.wizard.element.AAddButton;
import net.wangit.dev.wizard.element.AEUnit;
import net.wangit.dev.wizard.element.ARemoveButton;
import net.wangit.dev.wizard.unit.AListUnit;
import net.wangit.dev.wizard.unit.APage;
import net.wangit.dev.wizard.unit.AUnitGroup;
import net.wangit.framework.validation.ValidationResult;
import net.wangit.framework.validation.ValidationUtil;
import net.wangit.jdbc.DB;
import net.wangit.util.Checker;
import net.wangit.util.StringUtil;
import net.wangit.view.element.ElementComponent;
import net.wangit.view.unit.UnitComponent;
import net.wangit.view.unit.UnitFactory;


public abstract class TwoTableSuiteProcessor {

	protected String unitId;
	protected UnitComponent unit;
	protected String domain;
	protected boolean addGroup;
	protected String fatherTableName;
	protected String sonTableName;
	protected String linkedFields;
	protected Map<String, String> father2SonFields;
	protected Map<String, String> son2FatherFields;
	protected String groupId;
	protected String groupName;
	protected String page1Id;
	protected String page1Name;
	protected String queryUnitId;
	protected String queryUnitName;
	protected String listUnitId;
	protected String listUnitName;
	protected String formUnitId;
	protected String formUnitName;
	protected String sonListUnitId;
	protected String sonListUnitName;
	protected String page2Id;
	protected String page2Name;
	protected DB db;
	protected ActionContext ac;

	public TwoTableSuiteProcessor() {
		father2SonFields = new HashMap<String, String>();
		son2FatherFields = new HashMap<String, String>();
	}

	public void process(DB db, ActionContext ac, String unitId)
			throws Exception {
		init(db, ac, unitId);
		if (!invalid()) {
			ac.getActionResult().setSuccessful(false);
			return;
		}
		if (addGroup)
			AUnitGroup.create(db, groupId, groupName);
		createFathterTableUnits();
		createCommonUnits();
	}

	private void init(DB db, ActionContext ac, String unitId) {
		this.db = db;
		this.ac = ac;
		this.unitId = unitId;
		domain = ConsoleDomainUtil.getDomain(ac);
		unit = UnitFactory.getUnitWithoutClone("dev", unitId);
		fatherTableName = StringUtil
				.clearSpace(ac.getRequestParameter((new StringBuilder(String
						.valueOf(unitId))).append(".fathertablename")
						.toString()));
		sonTableName = StringUtil
				.clearSpace(ac.getRequestParameter((new StringBuilder(String
						.valueOf(unitId))).append(".sontablename").toString()));
		linkedFields = StringUtil
				.clearSpace(ac.getRequestParameter((new StringBuilder(String
						.valueOf(unitId))).append(".linkedfields").toString()));
		groupId = StringUtil
				.clearSpace(ac.getRequestParameter((new StringBuilder(String
						.valueOf(unitId))).append(".groupid").toString()));
		groupId = toLower(groupId);
		groupName = ac.getRequestParameter((new StringBuilder(String
				.valueOf(unitId))).append(".groupname").toString());
		page1Id = StringUtil
				.clearSpace(ac.getRequestParameter((new StringBuilder(String
						.valueOf(unitId))).append(".page1id").toString()));
		page1Id = toLower(page1Id);
		page1Name = ac.getRequestParameter((new StringBuilder(String
				.valueOf(unitId))).append(".page1name").toString());
		queryUnitId = StringUtil
				.clearSpace(ac.getRequestParameter((new StringBuilder(String
						.valueOf(unitId))).append(".queryunitid").toString()));
		queryUnitId = toLower(queryUnitId);
		queryUnitName = ac.getRequestParameter((new StringBuilder(String
				.valueOf(unitId))).append(".queryunitname").toString());
		listUnitId = StringUtil
				.clearSpace(ac.getRequestParameter((new StringBuilder(String
						.valueOf(unitId))).append(".listunitid").toString()));
		listUnitId = toLower(listUnitId);
		listUnitName = ac.getRequestParameter((new StringBuilder(String
				.valueOf(unitId))).append(".listunitname").toString());
		page2Id = StringUtil
				.clearSpace(ac.getRequestParameter((new StringBuilder(String
						.valueOf(unitId))).append(".page2id").toString()));
		page2Id = toLower(page2Id);
		page2Name = ac.getRequestParameter((new StringBuilder(String
				.valueOf(unitId))).append(".page2name").toString());
		formUnitId = StringUtil
				.clearSpace(ac.getRequestParameter((new StringBuilder(String
						.valueOf(unitId))).append(".formunitid").toString()));
		formUnitId = toLower(formUnitId);
		formUnitName = ac.getRequestParameter((new StringBuilder(String
				.valueOf(unitId))).append(".formunitname").toString());
		sonListUnitId = StringUtil
				.clearSpace(ac.getRequestParameter((new StringBuilder(String
						.valueOf(unitId))).append(".sonlistunitid").toString()));
		sonListUnitId = toLower(sonListUnitId);
		sonListUnitName = ac.getRequestParameter((new StringBuilder(String
				.valueOf(unitId))).append(".sonlistunitname").toString());
		addGroup = "1".equals(ac.getRequestParameter((new StringBuilder(String
				.valueOf(unitId))).append(".addgroup").toString()));
	}

	private String toLower(String id) {
		if (Checker.isEmpty(id))
			return id;
		else
			return id.toLowerCase();
	}

	private boolean invalid() throws Exception {
		ValidationResult vr = new ValidationResult(ac, true);
		vr.setUnitId(unitId);
		WizardUtil.validateTable(db, ac, vr, unit
				.getElementComponent("fathertablename"), fatherTableName);
		WizardUtil.validateTable(db, ac, vr, unit
				.getElementComponent("sontablename"), sonTableName);
		ValidationUtil.isNotNull(vr, ac, linkedFields, unit
				.getElementComponent("linkedfields"));
		ElementComponent lec = unit.getElementComponent("linkedfields");
		if (!Checker.isEmpty(linkedFields) && !isViladLinkFields()) {
			String error = LabelUtil.get(ac, "dev",
					"wizard.invalid_linked_fields");
			vr.addError(0, lec.getId(), ValidationUtil.getMessage(ac, lec,
					linkedFields, error, false, 0));
		} else {
			String array[][] = StringUtil.split(linkedFields, "/", "=");
			for (int i = 0; i < array.length; i++) {
				if (!ComponentUtil.existentColumn(db, fatherTableName,
						array[i][0])) {
					String error = LabelUtil.get(ac, "dev",
							"wizard.column_notfound", (new StringBuilder(String
									.valueOf(fatherTableName))).append(",")
									.append(array[i][0]).toString());
					vr.addError(0, lec.getId(), error);
				}
				if (!ComponentUtil
						.existentColumn(db, sonTableName, array[i][1])) {
					String error = LabelUtil.get(ac, "dev",
							"wizard.column_notfound", (new StringBuilder(String
									.valueOf(sonTableName))).append(",")
									.append(array[i][1]).toString());
					vr.addError(0, lec.getId(), error);
				}
			}

		}
		if (addGroup)
			ValidationUtil.isNotNull(vr, ac, groupId, unit
					.getElementComponent("groupid"));
		int count = 0;
		Map<String, String> map = new HashMap<String, String>();
		String units[][] = getUnits();
		for (int i = 0; i < units.length; i++) {
			String value = units[i][0];
			String id = units[i][1];
			if (!Checker.isEmpty(value)) {
				map.put(value, null);
				count++;
			}
			WizardUtil.validateUnitId(db, ac, vr, unit.getElementComponent(id),
					value);
		}

		if (count != map.size())
			vr.addError(LabelUtil.get(ac, "dev", "wizard.unitid_duplicate"));
		vr.finish();
		return vr.pass();
	}

	private boolean isViladLinkFields() {
		String array[][] = StringUtil.split(linkedFields, "/", "=");
		if (array != null) {
			for (int i = 0; i < array.length; i++) {
				String fields[] = array[i];
				if (fields.length != 2)
					return false;
				father2SonFields.put(fields[0], fields[1]);
				son2FatherFields.put(fields[1], fields[0]);
			}

			return father2SonFields.size() == son2FatherFields.size();
		} else {
			return false;
		}
	}

	private void createCommonUnits() throws Exception {
		APage.create(db, groupId, page2Id, page2Name);
		AEUnit.create(db, page2Id, formUnitId, 11, true);
		AEUnit.create(db, page2Id, sonListUnitId, 21, false);
		String sql = WizardUtil.getSonListUnitSql(db, domain, sonTableName,
				fatherTableName, father2SonFields, formUnitId);
		AListUnit.create(db, domain, groupId, sonListUnitId, sonListUnitName,
				sonTableName, null, sql, true, 0, false, page2Id);
		List<String> elements = Table2Unit.create(db, sonListUnitId,
				sonTableName, 2, son2FatherFields);
		AAddButton.create(db, ac, sonListUnitId, elements);
		ARemoveButton.create(db, ac, sonListUnitId, elements);
	}

	protected abstract void createFathterTableUnits() throws Exception;

	protected abstract String[][] getUnits();
}
